<?php
// $Id$

/**
 * @file
 * Theme callbacks to output the server status block.
 */

/**
 * Converts a channel and client list into one array structured according to channel/client
 * parents. All data is also validated for output.
 *
 * @param array $channels All channels on the server.
 * @param array $clients All clients connected to the server.
 * @param integer $parent_id The parent channel to build from, or 0 if there is no parent.
 * @param integer $depth Internal use only. Adds a depth field based on the recursion level.
 *
 * @return array A tree containing all channels and clients on the server.
 */
function _ventstatus_build_channel_tree($channels, $clients, $parent_id, $depth = 0) {
  $tree = array();
  
  if (isset($channels)) {
    foreach ($channels as $channel_id => $channel_info) {
      if ($channel_info['PID'] == $parent_id) {
        // Add channel details.
        $tree['channels'][$channel_id] = array(
          'name' => check_plain($channel_info['NAME']),
          'comment' => check_plain($channel_info['COMM']),
          'protected' => $channel_info['PROT']
        );
        
        // Recursively add sub-channels and clients.
        $tree['channels'][$channel_id]['children'] = _ventstatus_build_channel_tree($channels, $clients, $channel_id, $depth + 1);
      }
    }
  }
  
  if (isset($clients)) {
    foreach ($clients as $idx => $client_info) {
      // Otherwise, add client details.
      if ($client_info['CID'] == $parent_id) {
        $tree['clients'][] = array(
          'name' => $client_info['NAME'] != 'XXXXXXXX' ? check_plain($client_info['NAME']) : t('(hidden)'),
          'comment' => check_plain($client_info['COMM']),
          'comment_html' => filter_xss(_filter_url($client_info['COMM'], FILTER_FORMAT_DEFAULT), array('a')),
          'admin' => $client_info['ADMIN'] == 1 ? TRUE : FALSE,
          'phantom' => $client_info['PHAN'] == 1 ? TRUE : FALSE,
          'time' => $client_info['SEC'],
          'ping' => $client_info['PING']
        );
      }
    }
  }
  
  if (!empty($tree)) {
    $tree['depth'] = $depth;
  }
  
  return $tree;
}

/**
 * Format a time interval into a shortened, friendly format.
 * This is a modified version of format_interval().
 *
 * @param integer $time The length of the interval in seconds.
 * @param integer $granularity How many different units to display in the string.
 * @param $langcode Optional language code to translate to a language other than what
 *   is used to display the page.
 *
 * @return string A translated string representation of the interval.
 */
function ventstatus_format_interval($time, $granularity = 2, $langcode = NULL) {
  $units = array('@timew' => 604800, '@timed' => 86400, '@timeh' => 3600, '@timem' => 60, '@times' => 1);
  $output = '';
  
  foreach ($units as $arg => $interval) {
    if ($time > $interval) {
      $output .= (!empty($output) ? ' ' : '') . t($arg, array('@time' => floor($time / $interval)), $langcode);
      $time = $time % $interval;
      $granularity--;
    }
    
    if ($granularity == 0) {
      break;
    }
  }
  
  return !empty($output) ? $output : t('0s', array(), $langcode);
}

/**
 * Process variables for displaying server information.
 *
 * @param array $variables An array containing the following arguments:
 * - 'server' - An array containing server details.
 * - 'channels' - All channels on the server.
 * - 'clients' - All clients on the server.
 * After processing, the 'channels' and 'clients' fields will be unset and replaced
 * by a 'view' field containing the themed view for the selected display mode.
 * 
 * @see ventstatus-server.tpl.php
 */
function template_preprocess_ventstatus_server(&$variables) {
  // This function shouldn't ever be called with an empty server field.
  if (empty($variables['server'])) {
    $variables['server'] = array('error' => t('Unable to execute status query.'));
    return;
  }
  
  // If there was a problem running the status tool, the server field contains
  // an error message instead of an array containing server information.
  if (!is_array($variables['server'])) {
    $variables['server'] = array('error' => $variables['server']);
    return;
  }
  
  // If the tool was run, but there was a problem with the server, show the
  // tool's message and quit.
  if (isset($variables['server']['ERROR'])) {
    $variables['server']['error'] = t('Unable to get status report: @error-message',
      array('@error-message' => $variables['server']['ERROR'])
    );
    unset($variables['server']['ERROR']);
    return;
  }
  
  // General server information for both views.
  $info['name'] = check_plain($variables['server']['NAME']);
  $info['comment'] = filter_xss(_filter_url($variables['server']['COMMENT'], FILTER_FORMAT_DEFAULT), array('a'));
  $info['maxclients'] = $variables['server']['MAXCLIENTS'];
  $info['clientcount'] = $variables['server']['CLIENTCOUNT'];
  $info['uptime'] = $variables['server']['UPTIME'];
  
  $mode = variable_get('ventstatus_display_mode', VENTSTATUS_DISPLAY_NORMAL);
  if ($mode == VENTSTATUS_DISPLAY_SERVER_ONLY) {
    $server_view['platform'] = check_plain($variables['server']['PLATFORM']);
    $server_view['version'] = check_plain($variables['server']['VERSION']);
    $server_view['authmode'] = $variables['server']['AUTH'];
    
    // Remove the zero-based index of the list of possible codecs/formats that the server is using.
    $s = $variables['server']['VOICECODEC'];
    $i = strpos($s, ',');
    $server_view['voice_codec'] = substr($s, $i + 1, strlen($s) - $i - 1);
    
    $s = $variables['server']['VOICEFORMAT'];
    $i = strpos($s, ',');
    $server_view['voice_format'] = substr($s, $i + 1, strlen($s) - $i - 1);
    
    $variables['view'] = theme('ventstatus_server_view', $server_view);
  }
  else {
    // Organize channels and clients for output.
    $channel_view = _ventstatus_build_channel_tree($variables['channels'], $variables['clients'], 0);
    $variables['view'] = theme('ventstatus_channel_view', $channel_view);
  }
  
  // Remove unchecked data, just in case.
  $variables['server'] = $info;
  unset($variables['channels'], $variables['clients']);
}

/**
 * Process variables for creating a sort of channel browser, listing all channels and
 * clients in a tree form.
 *
 * @param array $variables An array containing the following arguments:
 * - 'channel_view' - An array containing channels, clients, and the current depth of
 *   the channel tree (which is normally 0 at this point).
 *
 * @see ventstatus-channel-view.tpl.php
 */
function template_preprocess_ventstatus_channel_view(&$variables) {
  $siblings = array();
  $clients = array();
  
  $view = $variables['view'];
  $depth = $view['depth'];
  
  if (isset($view['channels'])) {
    foreach ($view['channels'] as $channel_id => $channel) {
      $siblings[$channel_id] = theme('ventstatus_channel', $channel, $depth);
    }
  }
  
  if (isset($view['clients'])) {
    foreach ($view['clients'] as $idx => $client) {
      $clients[$idx] = theme('ventstatus_client', $client, $depth);
    }
  }
  
  $variables['view']['channels'] = $siblings;
  $variables['view']['clients'] = $clients;
}

/**
 * Process variables for displaying a channel and its contents. Note that this function is
 * effectively called recursively.
 * 
 * @param array $variables An array containing the following arguments:
 * - 'channel' - An array containing the channel's contents and details.
 * - 'depth' - The current tree depth.
 *
 * @see ventstatus-channel.tpl.php
 */
function template_preprocess_ventstatus_channel(&$variables) {
  $output = '';
  $children = $variables['channel']['children'];
  
  if ($children && isset($children['clients'])) {
    foreach ($children['clients'] as $idx => $client) {
      $output .= theme('ventstatus_client', $client, $children['depth']);
    }
  }
  
  if ($children && isset($children['channels'])) {
    foreach ($children['channels'] as $channel_id => $channel) {
      $output .= theme('ventstatus_channel', $channel, $children['depth']);
    }
  }
  
  $variables['channel']['children'] = $output;
}
